package top.v5it.japi.ddd.core.entity;

import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Objects;

/**
 * 异常响应实体
 *
 * @author zhanpu
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Slf4j
public class ErrorResult implements Serializable {

    private static final long serialVersionUID = 3832172379830886524L;

    /**
     * 响应时间
     */
    private final LocalDateTime timestamp = LocalDateTime.now(ZoneId.systemDefault());

    /**
     * 状态码
     */
    private final int status;

    /**
     * 返回编码
     */
    private final String error;

    /**
     * 错误描述
     */
    private final String message;

    /**
     * 请求路径
     */
    private final String path;

    /**
     * 错误
     *
     * @param template {@link ResultStatusTemplate}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(ResultStatusTemplate template, final String path) {
        return failure(
                template.getStatus()
                , template.toString()
                , template.getMessage()
                , path
        );
    }

    /**
     * 错误
     *
     * @param template {@link ResultStatusTemplate}
     * @param message  消息说明，参考{@link ResultStatus#getMessage()}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(ResultStatusTemplate template, final String message, final String path) {
        log.error("{}, {}", template, message);
        return failure(
                template.getStatus()
                , template.toString()
                , StrUtil.isNotBlank(message) ? message : template.getMessage()
                , path
        );
    }

    /**
     * 将一个object对象转换成{@link ErrorResult}，{@link ErrorResult}子类返回{@link ErrorResult}，否则返回null
     *
     * @param result 一个{@link ErrorResult}的子类入参
     * @return {@link ErrorResult}
     */
    public static ErrorResult of(Object result) {
        return Objects.nonNull(result) && result instanceof ErrorResult
                ? (ErrorResult) result
                : null;
    }

    /**
     * 自定义错误信息
     *
     * @param error   编码，参考{@link ResultStatus#name()}
     * @param message 消息说明，参考{@link ResultStatus#getMessage()}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(final String error, final String message, final String path) {
        return failure(400, error, message, path);
    }

    /**
     * 自定义错误信息
     *
     * @param status  状态码，参考{@link ResultStatus#getStatus()}
     * @param error   编码，参考{@link ResultStatus#name()}
     * @param message 消息说明，参考{@link ResultStatus#getMessage()}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(final int status, final String error, final String message, final String path) {
        return new ErrorResult(status, error, message, path);
    }
}
